1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.nio.cs.ext;
27
28 import java.nio.ByteBuffer;
29 import java.nio.CharBuffer;
30 import java.nio.charset.Charset;
31 import java.nio.charset.CharsetDecoder;
32 import java.nio.charset.CharsetEncoder;
33 import java.nio.charset.CoderResult;
34 import java.util.Arrays;
35 import sun.nio.cs.Surrogate;
36 import static sun.nio.cs.CharsetMapping.*;
37
38 public class HKSCS {
39
40 public static class Decoder extends DoubleByte.Decoder {
41 static int b2Min = 0x40;
42 static int b2Max = 0xfe;
43
44 private char[][] b2cBmp;
45 private char[][] b2cSupp;
46 private DoubleByte.Decoder big5Dec;
47
48 protected Decoder(Charset cs,
49 DoubleByte.Decoder big5Dec,
50 char[][] b2cBmp, char[][] b2cSupp)
51 {
52
53
54
55 super(cs, 0.5f, 1.0f, null, null, 0, 0);
56 this.big5Dec = big5Dec;
57 this.b2cBmp = b2cBmp;
58 this.b2cSupp = b2cSupp;
59 }
60
61 public char decodeSingle(int b) {
62 return big5Dec.decodeSingle(b);
63 }
64
65 public char decodeBig5(int b1, int b2) {
66 return big5Dec.decodeDouble(b1, b2);
67 }
68
69 public char decodeDouble(int b1, int b2) {
70 return b2cBmp[b1][b2 - b2Min];
71 }
72
73 public char decodeDoubleEx(int b1, int b2) {
74
75
76
77
78
79 return b2cSupp[b1][b2 - b2Min];
80 }
81
82 protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
83 byte[] sa = src.array();
84 int sp = src.arrayOffset() + src.position();
85 int sl = src.arrayOffset() + src.limit();
86
87 char[] da = dst.array();
88 int dp = dst.arrayOffset() + dst.position();
89 int dl = dst.arrayOffset() + dst.limit();
90
91 try {
92 while (sp < sl) {
93 int b1 = sa[sp] & 0xff;
94 char c = decodeSingle(b1);
95 int inSize = 1, outSize = 1;
96 char[] cc = null;
97 if (c == UNMAPPABLE_DECODING) {
98 if (sl - sp < 2)
99 return CoderResult.UNDERFLOW;
100 int b2 = sa[sp + 1] & 0xff;
101 inSize++;
102 if (b2 < b2Min || b2 > b2Max)
103 return CoderResult.unmappableForLength(2);
104 c = decodeDouble(b1, b2);
105 if (c == UNMAPPABLE_DECODING) {
106 c = decodeDoubleEx(b1, b2);
107 if (c == UNMAPPABLE_DECODING) {
108 c = decodeBig5(b1, b2);
109 if (c == UNMAPPABLE_DECODING)
110 return CoderResult.unmappableForLength(2);
111 } else {
112
113 outSize = 2;
114 }
115 }
116 }
117 if (dl - dp < outSize)
118 return CoderResult.OVERFLOW;
119 if (outSize == 2) {
120
121 da[dp++] = Surrogate.high(0x20000 + c);
122 da[dp++] = Surrogate.low(0x20000 + c);
123 } else {
124 da[dp++] = c;
125 }
126 sp += inSize;
127 }
128 return CoderResult.UNDERFLOW;
129 } finally {
130 src.position(sp - src.arrayOffset());
131 dst.position(dp - dst.arrayOffset());
132 }
133 }
134
135 protected CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
136 int mark = src.position();
137 try {
138 while (src.hasRemaining()) {
139 char[] cc = null;
140 int b1 = src.get() & 0xff;
141 int inSize = 1, outSize = 1;
142 char c = decodeSingle(b1);
143 if (c == UNMAPPABLE_DECODING) {
144 if (src.remaining() < 1)
145 return CoderResult.UNDERFLOW;
146 int b2 = src.get() & 0xff;
147 inSize++;
148 if (b2 < b2Min || b2 > b2Max)
149 return CoderResult.unmappableForLength(2);
150 c = decodeDouble(b1, b2);
151 if (c == UNMAPPABLE_DECODING) {
152 c = decodeDoubleEx(b1, b2);
153 if (c == UNMAPPABLE_DECODING) {
154 c = decodeBig5(b1, b2);
155 if (c == UNMAPPABLE_DECODING)
156 return CoderResult.unmappableForLength(2);
157 } else {
158 outSize = 2;
159 }
160 }
161 }
162 if (dst.remaining() < outSize)
163 return CoderResult.OVERFLOW;
164 if (outSize == 2) {
165 dst.put(Surrogate.high(0x20000 + c));
166 dst.put(Surrogate.low(0x20000 + c));
167 } else {
168 dst.put(c);
169 }
170 mark += inSize;
171 }
172 return CoderResult.UNDERFLOW;
173 } finally {
174 src.position(mark);
175 }
176 }
177
178 public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
179 if (src.hasArray() && dst.hasArray())
180 return decodeArrayLoop(src, dst);
181 else
182 return decodeBufferLoop(src, dst);
183 }
184
185 static void initb2c(char[][]b2c, String[] b2cStr)
186 {
187 for (int i = 0; i < b2cStr.length; i++) {
188 if (b2cStr[i] == null)
189 b2c[i] = DoubleByte.B2C_UNMAPPABLE;
190 else
191 b2c[i] = b2cStr[i].toCharArray();
192 }
193 }
194
195 }
196
197 public static class Encoder extends DoubleByte.Encoder {
198 private DoubleByte.Encoder big5Enc;
199 private char[][] c2bBmp;
200 private char[][] c2bSupp;
201
202 protected Encoder(Charset cs,
203 DoubleByte.Encoder big5Enc,
204 char[][] c2bBmp,
205 char[][] c2bSupp)
206 {
207 super(cs, null, null);
208 this.big5Enc = big5Enc;
209 this.c2bBmp = c2bBmp;
210 this.c2bSupp = c2bSupp;
211 }
212
213 public int encodeBig5(char ch) {
214 return big5Enc.encodeChar(ch);
215 }
216
217 public int encodeChar(char ch) {
218 int bb = c2bBmp[ch >> 8][ch & 0xff];
219 if (bb == UNMAPPABLE_ENCODING)
220 return encodeBig5(ch);
221 return bb;
222 }
223
224 public int encodeSupp(int cp) {
225 if ((cp & 0xf0000) != 0x20000)
226 return UNMAPPABLE_ENCODING;
227 return c2bSupp[(cp >> 8) & 0xff][cp & 0xff];
228 }
229
230 public boolean canEncode(char c) {
231 return encodeChar(c) != UNMAPPABLE_ENCODING;
232 }
233
234 protected CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {
235 char[] sa = src.array();
236 int sp = src.arrayOffset() + src.position();
237 int sl = src.arrayOffset() + src.limit();
238
239 byte[] da = dst.array();
240 int dp = dst.arrayOffset() + dst.position();
241 int dl = dst.arrayOffset() + dst.limit();
242
243 try {
244 while (sp < sl) {
245 char c = sa[sp];
246 int inSize = 1;
247 int bb = encodeChar(c);
248 if (bb == UNMAPPABLE_ENCODING) {
249 if (Character.isSurrogate(c)) {
250 int cp;
251 if ((cp = sgp().parse(c, sa, sp, sl)) < 0)
252 return sgp.error();
253 bb = encodeSupp(cp);
254 if (bb == UNMAPPABLE_ENCODING)
255 return CoderResult.unmappableForLength(2);
256 inSize = 2;
257 } else {
258 return CoderResult.unmappableForLength(1);
259 }
260 }
261 if (bb > MAX_SINGLEBYTE) {
262 if (dl - dp < 2)
263 return CoderResult.OVERFLOW;
264 da[dp++] = (byte)(bb >> 8);
265 da[dp++] = (byte)bb;
266 } else {
267 if (dl - dp < 1)
268 return CoderResult.OVERFLOW;
269 da[dp++] = (byte)bb;
270 }
271 sp += inSize;
272 }
273 return CoderResult.UNDERFLOW;
274 } finally {
275 src.position(sp - src.arrayOffset());
276 dst.position(dp - dst.arrayOffset());
277 }
278 }
279
280 protected CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
281 int mark = src.position();
282 try {
283 while (src.hasRemaining()) {
284 int inSize = 1;
285 char c = src.get();
286 int bb = encodeChar(c);
287 if (bb == UNMAPPABLE_ENCODING) {
288 if (Character.isSurrogate(c)) {
289 int cp;
290 if ((cp = sgp().parse(c, src)) < 0)
291 return sgp.error();
292 bb = encodeSupp(cp);
293 if (bb == UNMAPPABLE_ENCODING)
294 return CoderResult.unmappableForLength(2);
295 inSize = 2;
296 } else {
297 return CoderResult.unmappableForLength(1);
298 }
299 }
300 if (bb > MAX_SINGLEBYTE) {
301 if (dst.remaining() < 2)
302 return CoderResult.OVERFLOW;
303 dst.put((byte)(bb >> 8));
304 dst.put((byte)(bb));
305 } else {
306 if (dst.remaining() < 1)
307 return CoderResult.OVERFLOW;
308 dst.put((byte)bb);
309 }
310 mark += inSize;
311 }
312 return CoderResult.UNDERFLOW;
313 } finally {
314 src.position(mark);
315 }
316 }
317
318 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
319 if (src.hasArray() && dst.hasArray())
320 return encodeArrayLoop(src, dst);
321 else
322 return encodeBufferLoop(src, dst);
323 }
324
325 static char[] C2B_UNMAPPABLE = new char[0x100];
326 static {
327 Arrays.fill(C2B_UNMAPPABLE, (char)UNMAPPABLE_ENCODING);
328 }
329
330 static void initc2b(char[][] c2b, String[] b2cStr, String pua) {
331
332 int b2Min = 0x40;
333 Arrays.fill(c2b, C2B_UNMAPPABLE);
334 for (int b1 = 0; b1 < 0x100; b1++) {
335 String s = b2cStr[b1];
336 if (s == null)
337 continue;
338 for (int i = 0; i < s.length(); i++) {
339 char c = s.charAt(i);
340 int hi = c >> 8;
341 if (c2b[hi] == C2B_UNMAPPABLE) {
342 c2b[hi] = new char[0x100];
343 Arrays.fill(c2b[hi], (char)UNMAPPABLE_ENCODING);
344 }
345 c2b[hi][c & 0xff] = (char)((b1 << 8) | (i + b2Min));
346 }
347 }
348 if (pua != null) {
349 char c = '\ue000';
350 for (int i = 0; i < pua.length(); i++) {
351 char bb = pua.charAt(i);
352 if (bb != UNMAPPABLE_DECODING) {
353 int hi = c >> 8;
354 if (c2b[hi] == C2B_UNMAPPABLE) {
355 c2b[hi] = new char[0x100];
356 Arrays.fill(c2b[hi], (char)UNMAPPABLE_ENCODING);
357 }
358 c2b[hi][c & 0xff] = bb;
359 }
360 c++;
361 }
362 }
363 }
364 }
365 }